﻿using IcsSEMCtrl.Db;
using IcsSEMCtrl.Device.Observe;
using IcsSEMCtrl.Service.Logger;
using IcsSEMCtrl.Service.Material;
using IcsSEMCtrl.Util.Client;
using Lifter.Device;
using Lifter.Device.Dispatcher;
using Lifter.Device.Unit;
using Lifter.Event.Lifter;
using Lifter.Global;
using Lifter.Utility;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Threading;
using System.Timers;
using TKT.Lifter.CIM.Lifter.Device.Service;
using static TKT.Lifter.CIM.Lifter.Device.Unit.LifterTower;
using static TKT.Lifter.CIM.Lifter.Global.SysTemConstant;

namespace TKT.Lifter.CIM.Lifter.Device.Unit
{
    /// <summary>
    /// add by yangshl 2023/9/12
    /// 轿厢搬送逻辑控制主类
    /// </summary>
    public class ShuttleMaster : LocationUnit
    {
        /// <summary>
        /// 轿厢工作模式（接料,送料,接送同步）
        /// </summary>
        public enum ShuttleWorkMode
        {
            SHUTTLE_RECEIVE = 1,
            SHUTTLE_SEND,
            SHUTTLE_SENDANDRECEIVE
        }
        /// <summary>
        /// 轿厢下一步指令类型
        /// </summary>
        public enum ShuttleNextCommandType
        {
            NONE,
            MOVE,
            TRANSFER,
            WAIT,
            TRANSFERINWAIT,
            TRANSFEROUTWAIT
        }
        /// <summary>
        /// 轿厢判断下一步指令状态
        /// </summary>
        public enum ShuttleNextDoCommandStatus
        {
            OK,
            PortAlarm,
            ShuttleAlarm,
            EQPAlarm,
        }
        /// <summary>
        /// 轿厢做transfer动作时，Port状态标识
        /// </summary>
        public enum ShuttleTransferDownFlag
        {
            None,
            transferInPortDown,
            transferOutPortDown
        }
        /// <summary>
        /// 轿厢动作状态
        /// </summary>
        public enum ShuttleTransferStatus
        {
            Ready,
            Transfer,
            Move
        }
        private const string CLASS = "ShuttleMaster";
        private int shuttleFloor;//轿厢所在楼层
        public LifterSEM lftSem = null;
        private ShuttleWorkMode shuttleWorkModeType = ShuttleWorkMode.SHUTTLE_SENDANDRECEIVE;//轿厢工作模式（receive/send）
        private ShuttleNextCommandType nextCommandType = ShuttleNextCommandType.NONE;//轿厢执行下一步指令类型
        private bool allowDoTransfer = false;
        private System.Timers.Timer WaitForDoTransferTimer = new System.Timers.Timer();
        private int transferTimeOutCount = 0;//transfer超时等待时间
        private enumRIDState shuttleMasterStatus = enumRIDState.DOWN; //轿厢状态
        private enumShuttleMasterStateForAim shuttleMasterStatusForAim = enumShuttleMasterStateForAim.OutofService;//上报Host的轿厢状态
        private TransferWorkItem shuttleActiveCommand = new TransferWorkItem();//轿厢ShuttleActive指令
        private string locationID = "";//轿厢shuttleLocationChangge上报的LocationID(指令dest/source)
        private string shuttleLocationCommandID = ""; //轿厢shuttleLocationChangge上报的指令ID(指令CommandID)
        private ShuttleTransferDownFlag shuttleTransferDown = ShuttleTransferDownFlag.None;//TransferPort口是否Down标识
        private bool shuttleIsReadyFlag = false; //轿厢是否是Ready状态
        public bool IsOnlyUseBehindVehicle; //是否只使用后排轿厢
        private ShuttleTransferStatus transferStatus; //轿厢运行过程中的状态信息
        private int shuttleDestFloor; //轿厢目的地楼层

        private CimToPLCCommandInfo shuttleLocationCommand = null; //触发轿厢移动的指令信息，用于上报HOST shuttleLocation事件
        public delegate void SenserInfoDelegate(int value);
        public SenserInfoDelegate senser1F2FInfoDelegate;
        public SenserInfoDelegate senser3F4FInfoDelegate;

        public int ShuttleFloor { get => shuttleFloor; set => shuttleFloor = value; }
        internal ShuttleWorkMode ShuttleWorkModeType { get => shuttleWorkModeType; set => shuttleWorkModeType = value; }

        public override void Init()
        {
            base.Init();
            this.AddSubScribe();

            //初始化transfer是否执行的timer
            WaitForDoTransferTimer.Elapsed += new ElapsedEventHandler(WaitForDoTransfer);
            WaitForDoTransferTimer.Interval = 1000;
            IsOnlyUseBehindVehicle = "T".Equals(base.GetUserDefinedPropertyValue("IsOnlyUseBehindVehicle", "F", false));
        }
        /// <summary>
        /// add by yangshl 2023/9/21
        /// 等待是否还能进行tansfer动作
        /// </summary>
        private void WaitForDoTransfer(object sender, ElapsedEventArgs e)
        {
            WaitForDoTransferTimer.Stop();
            this.JudgeDoNextCommand();
        }
        /// <summary>
        /// add by yangshl 2023/9/15
        /// 添加Master轿厢点位订阅事件
        /// </summary>
        private void AddSubScribe()
        {
            this.I_MOVESTARTRPY.ObservableValueChanged += new DelegateObservableValueChanged(this.I_MOVESTARTRPY_ObservableValueChanged);
            this.I_TRANSFERSTARTRPY.ObservableValueChanged += new DelegateObservableValueChanged(this.I_TRANSFERSTARTRPY_ObservableValueChanged);
            this.I_SHUTTLEMOVECOMPLETE.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLEMOVECOMPLETE_ObservableValueChanged);
            this.I_SHUTTLEMOVEREADY.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLEMOVEREADY_ObservableValueChanged);
            //this.I_SHUTTLEFLOOR.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLEFLOOR_ObservableValueChanged);
            this._I_SHUTTLEFLOORVALUE.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLEFLOORVALUE_ObservableValueChanged);
            this.I_SHUTTLECVSTATUS.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLECVSTATUS_ObservableValueChanged);
            this.I_SHUTTLEDOWNRPY.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLEDOWNRPY_ObservableValueChanged);
            this.I_SHUTTLE1F2FSENSORIO.ObservableValueChanged += new DelegateObservableValueChanged(this.I_SHUTTLE1F2FSENSORIO_ObservableValueChanged);
            this.I_SHUTTLE3F4FSENSORIO.ObservableValueChanged += new DelegateObservableValueChanged(I_SHUTTLE3F4FSENSORIO_ObservableValueChanged);
/*            foreach (string current in base.Observables.Keys)
            {
                base.Observables[current].ObservableLogEvent += new delegateObservableLogEvent(this.ShuttleMaster_ObservableLogEvent);
            }*/
        }

        private void I_SHUTTLE3F4FSENSORIO_ObservableValueChanged(object sender, object value)
        {
            try
            {
                int SensorIOData = Convert.ToInt32(value);
                //委托前端界面实时显示
                if (this.senser3F4FInfoDelegate != null)
                {
                    this.senser3F4FInfoDelegate(SensorIOData);
                }
            }
            catch (Exception ex)
            {
                LogHelper.loggerError("在方法I_SHUTTLE3F4FSENSORIO_ObservableValueChanged中报错", ex);
            }
        }

        private void I_SHUTTLE1F2FSENSORIO_ObservableValueChanged(object sender, object value)
        {
            try
            {
                int SensorIOData = Convert.ToInt32(value);
                //委托前端界面实时显示
                if (this.senser1F2FInfoDelegate != null)
                {
                    this.senser1F2FInfoDelegate(SensorIOData);
                }
            }
            catch (Exception ex)
            {
                LogHelper.loggerError("在方法I_SHUTTLE1F2FSENSORIO_ObservableValueChanged中报错", ex);
            }
        }

        private void I_SHUTTLEDOWNRPY_ObservableValueChanged(object sender, object value)
        {
            if ((bool)value)
            {
                this.O_SHUTTLEDOWNREQ = false;
            }
        }

        /// <summary>
        /// 轿厢状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void I_SHUTTLECVSTATUS_ObservableValueChanged(object sender, object value)
        {
            enumShuttleMasterStateForAim newShuttleMasterStateForAim = enumShuttleMasterStateForAim.OutofService;
            switch ((short)value)
            {
                case 0:
                    this.ShuttleMasterStatus = enumRIDState.DOWN;
                    newShuttleMasterStateForAim = enumShuttleMasterStateForAim.OutofService;
                    this.ChangeShuttleStateForHost(newShuttleMasterStateForAim);
                    if (this.lftSem.DeviceState != enumRIDState.DOWN)
                    {
                        this.lftSem.DeviceState = enumRIDState.DOWN;
                    }
                    break;
                case 1:
                    this.ShuttleMasterStatus = enumRIDState.IDLE;
                    newShuttleMasterStateForAim = enumShuttleMasterStateForAim.InService;
                    this.ChangeShuttleStateForHost(newShuttleMasterStateForAim);
                    if (this.lftSem.DeviceState != enumRIDState.IDLE)
                    {
                        this.lftSem.DeviceState = enumRIDState.IDLE;
                    }
                    break;
                case 2:
                    this.ShuttleMasterStatus = enumRIDState.RUN;
                    newShuttleMasterStateForAim = enumShuttleMasterStateForAim.InService;
                    this.ChangeShuttleStateForHost(newShuttleMasterStateForAim);
                    if (this.lftSem.DeviceState != enumRIDState.RUN)
                    {
                        this.lftSem.DeviceState = enumRIDState.RUN;
                    }
                    break;
            }
            LogHelper.loggerInfo("轿厢状态改变，当前轿厢状态为:" + this.ShuttleMasterStatus);
            this.lftSem.Vehicles["VEHICLE:1"].InnerPublishEvent(VehicleEvent.VehicleEventType.RUN_IDLE_DOWN);
        }
        /// <summary>
        /// 改变轿厢上报Host状态，并且上报host
        /// </summary>
        private void ChangeShuttleStateForHost(enumShuttleMasterStateForAim newShuttleMasterStateForAim)
        {
            if (this.shuttleMasterStatusForAim != newShuttleMasterStateForAim)
            {
                this.shuttleMasterStatusForAim = newShuttleMasterStateForAim;
                if (newShuttleMasterStateForAim == enumShuttleMasterStateForAim.InService)
                {
                    this.lftSem.SecsDriver.SendMessage("S6F11", "403", this);
                }
                else
                {
                    this.lftSem.SecsDriver.SendMessage("S6F11", "404", this);
                }
            }
        }
        /// <summary>
        /// 设备重报警恢复后，设备初始化，然后重新下发Move/Transfer指令
        /// </summary>
        public void MachineAlarmResumeAction()
        {
            //清空所有的指令（transfer/Move）
            this.O_MOVETO = 0;
            this.O_MOVESTARTREQ = false;
            this.O_TRANSFERSTARTREQ = false;
            //获取所有的轿厢buffer
            foreach (Vehicle vehicle in this.lftSem.Vehicles.Values)
            {
                if (vehicle != null)
                {
                    vehicle.O_CVFROM = 0;
                    vehicle.O_CVTO = 0;
                }
            }
            foreach (TransferWorkItem transferWorkItem in this.lftSem.LDispatcher.workList)
            {
                //上报MCS transferResumed状态
                if (transferWorkItem.TransferState == enumTransferState.PAUSED)
                {
                    this.lftSem.SecsDriver.SendMessage("S6F11", "210", transferWorkItem);
                }
            }
            //this.lftSem.LDispatcher.DoFirstMoveCommand();
        }
        /// <summary>
        /// 设备重报警，暂停指令
        /// </summary>
        public void MachineAlarmPauseAction()
        {
            //清空所有的指令（transfer/Move）
            this.O_MOVETO = 0;
            this.O_MOVESTARTREQ = false;
            this.O_TRANSFERSTARTREQ = false;
            //获取所有的轿厢buffer
            foreach (Vehicle vehicle in this.lftSem.Vehicles.Values)
            {
                if (vehicle != null)
                {
                    vehicle.O_CVFROM = 0;
                    vehicle.O_CVTO = 0;
                }
            }
        }
        /// <summary>
        /// add by yangshl 2023/9/12
        /// 判断轿厢内是否为空
        /// </summary>
        /// <returns>轿厢是否为空</returns>
        public bool ShuttleIsEmpty()
        {
            bool result = true;
            
            List<TransferWorkItem> transferCommands = this.lftSem.LDispatcher.GetTransferCommandOnShuttle();
            //是否存在轿厢内的搬送指令
            if (transferCommands.Count > 0)
            {
                foreach (TransferWorkItem transferWork in transferCommands)
                {
                    foreach (Vehicle vehicle in lftSem.GetVehicleAll().Values)
                    {
                        if (transferWork.CommandID.Equals(vehicle.CommandId))
                        {
                            result = false;
                            return result;
                        }
                    }
                }
            }
            return result;
        }
        #region Master轿厢点位部分
        /// <summary>
        /// 轿厢指令目的地楼层点位
        /// </summary>
        public short O_MOVETO
        {
            set
            {
                base.Observables["MOVETO"].AsShort = value;
                this.shuttleDestFloor = value;
            }
        }
        /// <summary>
        /// 轿厢实时位置
        /// </summary>
        public short I_SHUTTLELOCATION
        {
            get
            {
                return base.Observables["SHUTTLELOCATION"].AsShort;
            }
        }
        /// <summary>
        /// 轿厢移动完成上报
        /// </summary>
        public Observable I_SHUTTLEMOVECOMPLETE
        {
            get
            {
                return base.Observables["SHUTTLEMOVECOMPLETE"];
            }
        }
        /// <summary>
        /// 轿厢移动完成回复
        /// </summary>
        public bool O_SHUTTLEMOVECOMPLETERPY
        {
            set
            {
                base.Observables["SHUTTLEMOVECOMPLETERPY"].AsBoolean = value;
            }
        }
        /// <summary>
        /// 轿厢移动开始指令
        /// </summary>
        public bool O_MOVESTARTREQ
        {
            set
            {
                base.Observables["MOVESTARTREQ"].AsBoolean = value;
            }
        }
        //轿厢高速设置值
        public short O_SHUTTLEHIGHSPEEDVALUE
        {
            set
            {
                base.Observables["SHUTTLEHIGHSPEEDVALUE"].AsShort = value;
            }
        }
        //轿厢中速设置值
        public short O_SHUTTLEMEDIUMSPEEDVALUE
        {
            set
            {
                base.Observables["SHUTTLEMEDIUMSPEEDVALUE"].AsShort = value;
            }
        }
        //轿厢低速设置值
        public short O_SHUTTLELOWSPEEDVALUE
        {
            set
            {
                base.Observables["SHUTTLELOWSPEEDVALUE"].AsShort = value;
            }
        }
        //轿厢高速设置信号
        public bool O_SHUTTLEHIGHSPEED
        {
            set
            {
                base.Observables["SHUTTLEHIGHSPEED"].AsBoolean = value;
            }
        }
        //轿厢中速设置信号
        public bool O_SHUTTLEMEDIUMSPEED
        {
            set
            {
                base.Observables["SHUTTLEMEDIUMSPEED"].AsBoolean = value;
            }
        }
        //轿厢低速设置信号
        public bool O_SHUTTLELOWSPEED
        {
            set
            {
                base.Observables["SHUTTLELOWSPEED"].AsBoolean = value;
            }
        }
        /// <summary>
        /// 轿厢移动开始指令回复
        /// </summary>
        public Observable I_MOVESTARTRPY
        {
            get
            {
                return base.Observables["MOVESTARTRPY"];
            }
        }
        /// <summary>
        /// 轿厢GET/PUT开始指令
        /// </summary>
        public bool O_TRANSFERSTARTREQ
        {
            set
            {
                Console.WriteLine("TRANSFERSTARTREQ + " + value);
                base.Observables["TRANSFERSTARTREQ"].AsBoolean = value;
            }
        }
        /// <summary>
        /// 轿厢GET/PUT开始指令回复
        /// </summary>
        public Observable I_TRANSFERSTARTRPY
        {
            get
            {
                return base.Observables["TRANSFERSTARTRPY"];
            }
        }
        /// <summary>
        /// 轿厢准备接收移动指令
        /// </summary>
        public Observable I_SHUTTLEMOVEREADY
        {
            get
            {
                return base.Observables["SHUTTLEMOVEREADY"];
            }
        }
        /// <summary>
        /// 轿厢状态（IDLE,RUN,DOEN）
        /// </summary>
        public Observable I_SHUTTLECVSTATUS
        {
            get
            {
                return base.Observables["SHUTTLECVSTATUS"];
            }
        }
        /// <summary>
        /// 轿厢所在楼层上报信号
        /// </summary>
        public Observable I_SHUTTLEFLOOR
        {
            get
            {
                return base.Observables["SHUTTLEFLOOR"];
            }
        }
        /// <summary>
        /// /轿厢所在楼层值
        /// </summary>
        public short I_SHUTTLEFLOORVALUE
        {
            get
            {
                return base.Observables["SHUTTLEFLOORVALUE"].AsShort;
            }
        }
        public Observable _I_SHUTTLEFLOORVALUE
        {
            get
            {
                return base.Observables["SHUTTLEFLOORVALUE"];
            }
        }
        public bool O_SHUTTLEDOWNREQ
        {
            set
            {
                base.Observables["SHUTTLEDOWNREQ"].AsBoolean = value;
            }
        }
        public Observable I_SHUTTLEDOWNRPY
        {
            get
            {
                return base.Observables["SHUTTLEDOWNRPY"];
            }
        }
        public Observable I_SHUTTLE1F2FSENSORIO
        {
            get
            {
                return base.Observables["SHUTTLE1F2FSENSORIO"];
            }
        }
        public Observable I_SHUTTLE3F4FSENSORIO
        {
            get
            {
                return base.Observables["SHUTTLE3F4FSENSORIO"];
            }
        }
        public short I_SHUTTLE1F2FSENSORIOVALUE
        {
            get
            {
                return base.Observables["SHUTTLE1F2FSENSORIO"].AsShort;
            }
        }
        public short I_SHUTTLE3F4FSENSORIOVALUE
        {
            get
            {
                return base.Observables["SHUTTLE3F4FSENSORIO"].AsShort;
            }
        }
        #endregion
        #region 轿厢点位事件绑定方法
        /// <summary>
        /// 轿厢所在楼层上报信号
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        /*        private void I_SHUTTLEFLOOR_ObservableValueChanged(object sender, object value)
                {
                    if ((bool)value)
                    {
                        this.shuttleFloor = this.I_SHUTTLEFLOORVALUE;
                    }
                }*/

        /// <summary>
        /// 轿厢所在楼层上报信号
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void I_SHUTTLEFLOORVALUE_ObservableValueChanged(object sender, object value)
        {
            this.shuttleFloor = this.I_SHUTTLEFLOORVALUE;
        }
        /// <summary>
        /// 轿厢移动完成，准备接收下一条指令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void I_SHUTTLEMOVEREADY_ObservableValueChanged(object sender, object value)
        {
            Console.WriteLine("轿厢READY -"+(bool)value);
            LogHelper.loggerInfo("轿厢READY信号上报，信号为:" + (bool)value);
            this.ShuttleIsReadyFlag = (bool)value;
            if ((bool)value)
            {
                this.transferStatus = ShuttleTransferStatus.Ready;
                //清除轿厢Move指令，清除轿厢transfer指令
                this.O_MOVETO = 0;
                foreach (Vehicle vehicle in this.lftSem.Vehicles.Values)
                {
                    vehicle.To = 0;
                    vehicle.From = 0;
                }

                //判断指令集合是否有值
                if (this.lftSem.LDispatcher.workList != null && this.lftSem.LDispatcher.workList.Count > 0)
                {
                    //判断下一条指令类型
                    this.JudgeDoNextCommand();
                }
                else
                {
                    this.lftSem.LDispatcher.refreshCommandTimer.Start();
                    LogHelper.loggerInfo("指令集合为空，启动Timer刷新扫描指令集合");
                }
            }
        }
        /// <summary>
        /// 判断下一步执行指令类型
        /// </summary>
        public void JudgeDoNextCommand()
        {
            //判断设备状态跟轿厢状态是否正常
            ShuttleNextDoCommandStatus nextDoCommandStatus = this.ShuttleDoCommandStatus();
            if (nextDoCommandStatus == ShuttleNextDoCommandStatus.ShuttleAlarm || nextDoCommandStatus == ShuttleNextDoCommandStatus.EQPAlarm)
            {
                this.WaitForDoTransferTimer.Start();
            }
            else
            {
                //判断是否能执行transfer指令
                switch (this.DoNextCommand())
                {
                    case ShuttleNextCommandType.NONE:
                        LogHelper.loggerInfo("判断设备下一步动作为:[NONE]");
                        break;
                    case ShuttleNextCommandType.MOVE:
                        LogHelper.loggerInfo("判断设备下一步动作为:[MOVE]");
                        this.DoShuttleCommand();
                        this.transferTimeOutCount = 0;
                        break;
                    case ShuttleNextCommandType.TRANSFER:
                        LogHelper.loggerInfo("判断设备下一步动作为:[TRANSFER]");
                        //当前楼层的Port状态为 Down
                        //case1:所有Port口Down,整个楼层Down，且状态为Down
                        //      case1:轿厢继续执行Move动作（下Move指令时需要排出Port状态为down的指令）
                        //      case2:轿厢继续执行Transfer动作（需要判断Port口状态）
                        //case2:1个Port口Down,整个楼层Down,且状态为Down;
                        //      case1:轿厢执行Move动作
                        if (nextDoCommandStatus == ShuttleNextDoCommandStatus.PortAlarm)
                        {
                            //轿厢做Move动作
                            this.DoShuttleCommand();
                            this.transferTimeOutCount = 0;
                        }
                        else
                        {
                            int timeOutCountTranfer = int.Parse(this.lftSem.GetUserDefinedPropertyValue("Transfer_TimeOut_Count", "1000", true));
                            //transferTimeOutCount = 100;
                            if (transferTimeOutCount <= timeOutCountTranfer)
                            {
                                //执行轿厢Transfer动作
                                this.DoShuttleTransfer();
                            }
                            else
                            {
                                //判断是否有TransferInPortDown 或者TransferOutPortDown
                                if (this.ShuttleTransferDown == ShuttleTransferDownFlag.transferInPortDown)//TransferInPortDown 轿厢执行Move动作
                                {
                                    //直接轿厢移动
                                    this.DoShuttleCommand();
                                    this.transferTimeOutCount = 0;
                                }
                                else if (this.ShuttleTransferDown == ShuttleTransferDownFlag.transferOutPortDown)//TransferOutPortDown 
                                {
                                    //轿厢Down,报警，
                                    this.O_SHUTTLEDOWNREQ = true;
                                    //轿厢所有指令上报 MCS TransferPaused事件
                                    List<TransferWorkItem> transferWorkItems = this.lftSem.LDispatcher.GetTransferCommandOnShuttle();
                                    Thread.Sleep(2000);
                                    foreach (LifterPort lifterPort in this.lftSem.LifterPorts.Values)
                                    {
                                        if (lifterPort.Floor == this.shuttleFloor && lifterPort.LifterPortState == enumRIDState.DOWN && lifterPort.PortInOutMode == enumLifterPortDirection.OUT)
                                        {
                                            foreach (TransferWorkItem transferWorkItem in transferWorkItems)
                                            {
                                                LifterPort lifterPortByCommand = this.lftSem.GetLifterPort(transferWorkItem.Dest);
                                                if (lifterPortByCommand != null && lifterPortByCommand.HostID.Equals(lifterPort.HostID))
                                                {
                                                    transferWorkItem.TransferState = enumTransferState.PAUSED;
                                                }
                                                else
                                                {
                                                    ConveyorBuffer conveyorBufferByCommand = this.lftSem.GetConveyorBuffer(transferWorkItem.Dest);
                                                    if (conveyorBufferByCommand != null && conveyorBufferByCommand.LifterPortID.Equals(lifterPort.ElementId))
                                                    {
                                                        transferWorkItem.TransferState = enumTransferState.PAUSED;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    this.transferTimeOutCount = 0;
                                }
                                else
                                {
                                    //直接轿厢移动
                                    this.DoShuttleCommand();
                                    Console.WriteLine("transferActionTimeOut------DoShuttleCommand");
                                    LogHelper.loggerInfo("轿厢Transfer超时，直接做Move动作");
                                    this.transferTimeOutCount = 0;
                                }
                            }
                        }
                        break;
                    //执行轿厢入料等待
                    case ShuttleNextCommandType.TRANSFERINWAIT:
                        LogHelper.loggerInfo("判断设备下一步动作为:[TRANSFERINWAIT]");
                        int timeOutCount = int.Parse(this.lftSem.GetUserDefinedPropertyValue("Transfer_TimeOut_Count", "1000", true));
                        if (transferTimeOutCount <= timeOutCount)
                        {
                            if (this.lftSem.isWaitCVMaterialIsNull)
                            {
                                //TransferIn未超时的情况下，判断当前楼层所有入料CV和Port口上是否有物料
                                //有：等待物料进入轿厢
                                //无：轿厢直接做move
                                if (this.JudgeMaterialOnCVOrPortByFloor())
                                {
                                    this.WaitForDoTransferTimer.Start();
                                    //等待时间
                                    this.transferTimeOutCount++;
                                }
                                else
                                {
                                    this.DoShuttleCommand();
                                    this.transferTimeOutCount = 0;
                                }
                            }
                            else
                            {
                                this.WaitForDoTransferTimer.Start();
                                //等待时间
                                this.transferTimeOutCount++;
                            }
                        }
                        else
                        {
                            this.DoShuttleCommand();
                            this.transferTimeOutCount = 0;
                        }
                        break;
                    //执行轿厢出料等待
                    case ShuttleNextCommandType.TRANSFEROUTWAIT:
                        LogHelper.loggerInfo("判断设备下一步动作为:[TRANSFEROUTWAIT]");
                        //this.WaitForDoTransferTimer.Start();//一直等待出料
                        this.DoShuttleCommand();
                        this.transferTimeOutCount = 0;
                        break;
                }
            }
        }
        private void DoShuttleCommand()
        {
            //判断设备状态
            if (!this.lftSem.LDispatcher.JudgeEquipmentTransferStatus())
            {
                //记录Log或弹窗提醒（设备状态为Down或设备模式为Pause）
                LogHelper.loggerInfo("设备状态为Down或设备模式为Pause，在方法[DoShuttleCommand]中");
                this.WaitForDoTransferTimer.Start();
                return;
            }
            //创建轿厢Move指令
            CimToPLCCommandInfo floor = this.lftSem.LDispatcher.CreateShuttleMoveCommand();
            //判断返回的楼层是否为0层
            if (floor.Floor == 0)
            {
                //Timer监测开始
                this.lftSem.LDispatcher.refreshCommandTimer.Start();
            }
            else if (floor.Floor == this.ShuttleFloor)//执行Move指令逻辑，判断创建的Move指令跟轿厢是否位于同一楼层
            {
                //判断执行搬送动作
                this.DoShuttleTransfer();
                LogHelper.loggerInfo(string.Format("Move指令的目的地楼层[{0}]，跟轿厢当前楼层[{1}]，位于同一楼层,执行搬送动作", floor.Floor, this.shuttleFloor));
                
            }
            else//给PLC下move指令
            {
                this.DoShuttleMasterMove(floor);
                LogHelper.loggerInfo(string.Format("Move指令的目的地楼层[{0}]，跟轿厢当前楼层[{1}]，位于不同楼层,执行Move动作", floor.Floor, this.shuttleFloor));
            }
        }
        /// <summary>
        /// 轿厢移动完成上报
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void I_SHUTTLEMOVECOMPLETE_ObservableValueChanged(object sender, object value)
        {
            LogHelper.loggerInfo("轿厢移动完成，信号点位：" + (bool)value);
            if ((bool)value)
            {
                //清除Move指令(轿厢Ready信号上报，必须是轿厢指令为空的情况)
                this.O_MOVETO = 0;
                //二次清除轿厢开始移动信号
                this.O_MOVESTARTREQ = false;
                //轿厢移动完成回复On
                this.O_SHUTTLEMOVECOMPLETERPY = (bool)value;

/*                if (!string.IsNullOrEmpty(this.LocationID))
                {
                    //上报Host ShuttleLocation事件
                    this.lftSem.SecsDriver.SendMessage("S6F11", "603", this);
                    LogHelper.loggerInfo("轿厢移动完成，上报Host ShuttleLocation（603）事件, LocationID:" + this.LocationID);
                    Console.WriteLine("轿厢移动完成，上报Host ShuttleLocation（603）事件, LocationID:" + this.LocationID);
                    this.LocationID = "";
                }*/
            }
            else
            {
                try
                {
                    ConveyorBuffer conveyorBuffer = this.lftSem.GetConveyorBuffer(this.ShuttleLocationCommand.TransferWorkItem.Dest);
                    if (conveyorBuffer != null)
                    {
                        LifterPort lifterPortByConvey = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                        //目的地不等于当前楼层
                        if (lifterPortByConvey != null && lifterPortByConvey.Floor == this.shuttleFloor)
                        {
                            this.LocationID = this.ShuttleLocationCommand.TransferWorkItem.Dest;
                            //上报MCS shuttleLocation事件
                            this.lftSem.SecsDriver.SendMessage("S6F11", "603", this);
                            LogHelper.loggerInfo("轿厢移动完成，上报Host ShuttleLocation（603）事件, LocationID:" + this.LocationID);
                            Console.WriteLine("轿厢移动完成，上报Host ShuttleLocation（603）事件, LocationID:" + this.LocationID);
                            this.LocationID = "";
                        }
                    }
                    else
                    {
                        LifterPort lifterPortLoc = this.lftSem.GetLifterPort(this.shuttleLocationCommand.TransferWorkItem.Dest);
                        if (lifterPortLoc != null)
                        {
                            if (lifterPortLoc.Floor == this.shuttleFloor)
                            {
                                this.LocationID = this.shuttleLocationCommand.TransferWorkItem.Dest;
                                //上报MCS shuttleLocation事件
                                this.lftSem.SecsDriver.SendMessage("S6F11", "603", this);
                                LogHelper.loggerInfo("轿厢移动完成，上报Host ShuttleLocation（603）事件, LocationID:" + this.LocationID);
                                Console.WriteLine("轿厢移动完成，上报Host ShuttleLocation（603）事件, LocationID:" + this.LocationID);
                                this.LocationID = "";
                            }
                        }
                    }

                    //轿厢移动完成回复Off
                    this.O_SHUTTLEMOVECOMPLETERPY = (bool)value;
                    Thread.Sleep(200);
                    if (this.ShuttleActiveCommand != null && !string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                    {
                        //判断ShuttleActiveCommand是否需要出料
                        LifterPort lifterPort = this.lftSem.GetLifterPort(shuttleActiveCommand.Dest);
                        if (lifterPort != null && lifterPort.Floor == this.ShuttleFloor)
                        {
                            //上报ShuttleIdle（408）事件
                            this.lftSem.SecsDriver.SendMessage("S6F11", "408", this);
                            LogHelper.loggerInfo(this.HostID + "触发:上报ShuttleIdle（408）事件");
                            Console.WriteLine(this.HostID + "触发:上报ShuttleIdle（408）事件");
                            this.ShuttleActiveCommand.CommandID = "";
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.loggerError("在方法I_SHUTTLEMOVECOMPLETE_ObservableValueChanged中报错",ex);
                }
                //记录搬送结束时间
                this.lftSem.transferEndTime = DateTime.Now;
                this.lftSem.AddDataStatisticByDay(LifterSEM.statisticTimeType.TRANSFERTIME);
            }
        }
        /// <summary>
        /// 轿厢GET/PUT开始指令回复
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void I_TRANSFERSTARTRPY_ObservableValueChanged(object sender, object value)
        {
            if ((bool)value)
            {
                this.O_TRANSFERSTARTREQ = false;
            }
        }
        /// <summary>
        /// 轿厢移动开始指令回复
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="value"></param>
        private void I_MOVESTARTRPY_ObservableValueChanged(object sender, object value)
        {
            if ((bool)value)
            {
                this.O_MOVESTARTREQ = false;
            }
            LogHelper.loggerInfo($"轿厢移动开始指令回复信号[{(bool)value}]");
        }
        #endregion
        /// <summary>
        /// add by yangshl 2023/9/18
        /// 执行轿厢Master移动指令
        /// </summary>
        public void DoShuttleMasterMove(CimToPLCCommandInfo cimToPLCCommandInfo)
        {
            //下发move指令
            this.O_MOVETO = (short)cimToPLCCommandInfo.Floor;
            //启动轿厢移动指令
            this.O_MOVESTARTREQ = true;
            this.transferStatus = ShuttleTransferStatus.Move;
            LogHelper.loggerInfo("下发轿厢开始移动指令，移动目的地楼层:" + cimToPLCCommandInfo.Floor);
            Console.WriteLine("SHUTTLEMOVE:"+ cimToPLCCommandInfo.Floor);
            //MCS shuttleLocationChange事件的CommandID字段赋值
            this.ShuttleLocationCommandID = cimToPLCCommandInfo.TransferWorkItem.CommandID;

            ConveyorBuffer conveyorBuffer = this.lftSem.GetConveyorBuffer(cimToPLCCommandInfo.TransferWorkItem.Source);
            if (conveyorBuffer != null)
            {
                LifterPort lifterPortByConvey = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                //目的地不等于当前楼层,起始地等于当前楼层
                if (lifterPortByConvey != null && lifterPortByConvey.Floor == this.shuttleFloor)
                {
                    this.LocationID = cimToPLCCommandInfo.TransferWorkItem.Source;
                    //上报MCS shuttleLocation事件
                    this.lftSem.SecsDriver.SendMessage("S6F11", "603", this);
                    string message = string.Format("上报MCS shuttleLocation(603)事件,指令ID为:[{0}],LocationID为:[{1}]", cimToPLCCommandInfo.TransferWorkItem.CommandID, this.LocationID);
                    LogHelper.loggerInfo(message);
                    this.LocationID = "";
                }
            }
            else
            {
                LifterPort lifterPortLoc = this.lftSem.GetLifterPort(cimToPLCCommandInfo.TransferWorkItem.Source);
                if (lifterPortLoc != null)
                {
                    if (lifterPortLoc.Floor == this.shuttleFloor)
                    {
                        this.LocationID = cimToPLCCommandInfo.TransferWorkItem.Source;
                        //上报MCS shuttleLocation事件
                        this.lftSem.SecsDriver.SendMessage("S6F11", "603", this);
                        string message = string.Format("上报MCS shuttleLocation(603)事件,指令ID为:[{0}],LocationID为:[{1}]", cimToPLCCommandInfo.TransferWorkItem.CommandID, this.LocationID);
                        LogHelper.loggerInfo(message);
                        this.LocationID = "";
                    }
                }
            }

            if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID) && cimToPLCCommandInfo.TransferWorkItem.TransferState == enumTransferState.ONSHUTTLE)
            {
                Thread.Sleep(200);
                this.ShuttleActiveCommand.CommandID = cimToPLCCommandInfo.TransferWorkItem.CommandID;
                this.ShuttleActiveCommand.Dest = cimToPLCCommandInfo.TransferWorkItem.Dest;
                //上报MCS shuttleActive事件
                this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                LogHelper.loggerInfo("上报MCS shuttleActive(407)事件");
            }

            //记录搬送时间
            this.lftSem.transferStartTime = DateTime.Now;
        }
        /// <summary>
        /// add by yangshl 2023/10/08
        /// 判断当前楼层有一个Port口状态为Down,及楼层为Down
        /// </summary>
        /// <returns></returns>
        private bool JudgeFloorStatusByPort()
        {
            bool floorDownStatus = true;
            List<LifterPort> lifterPorts = this.lftSem.GetLifterPortByFloor(this.ShuttleFloor);
            if (lifterPorts != null && lifterPorts.Count > 0)
            {
                foreach (LifterPort lifterPort in lifterPorts)
                {
                    //判断Port口是否为down
                    if (lifterPort.LifterPortState != enumRIDState.DOWN)
                    {
                        if (lifterPort.PortInOutMode == enumLifterPortDirection.OUT)
                        {
                            if (lifterPort.IsOutputEnable)
                            {
                                floorDownStatus = false;
                            }
                            else
                            {
                                floorDownStatus = true;
                                break;
                            }
                        }
                        else
                        {
                            floorDownStatus = false;
                        }
                    }
                    else
                    {
                        floorDownStatus = true;
                        break;
                    }
                }
            }
            else
            {
                //记录Log或弹窗提示，当前楼层没有port口
                floorDownStatus = true;
            }
            return floorDownStatus;
        }
        /// <summary>
        /// add by yangshl 2023/10/08
        /// 判断当前楼层所有Port口状态为down,及楼层为down
        /// </summary>
        /// <returns></returns>
        private bool JudgeFloorStatusByAllPort()
        {
            bool floorDownStatus = true;
            List<LifterPort> lifterPorts = this.lftSem.GetLifterPortByFloor(this.ShuttleFloor);
            if (lifterPorts != null && lifterPorts.Count > 0)
            {
                foreach (LifterPort lifterPort in lifterPorts)
                {
                    //判断Port口是否为down
                    if (lifterPort.LifterPortState != enumRIDState.DOWN)
                    {
                        if (lifterPort.PortInOutMode == enumLifterPortDirection.OUT)
                        {
                            if (lifterPort.IsOutputEnable)
                            {
                                floorDownStatus = false;
                                break;
                            }
                            else
                            {
                                floorDownStatus = true;
                            }
                        }
                        else
                        {
                            floorDownStatus = false;
                            break;
                        }
                    }
                    else
                    {
                        floorDownStatus = true;
                    }
                }
            }
            else
            {
                //记录Log或弹窗提示，当前楼层没有port口
                floorDownStatus = true;
            }
            return floorDownStatus;
        }
        public ShuttleNextDoCommandStatus ShuttleDoCommandStatus()
        {
            //判断设备状态
            if (!this.lftSem.LDispatcher.JudgeEquipmentTransferStatus())
            {
                //记录Log或弹窗提醒（设备状态为Down或设备模式为Pause）
                LogHelper.loggerInfo("设备状态为Down或设备模式为Pause,在方法[ShuttleDoCommandStatus]中");
                return ShuttleNextDoCommandStatus.EQPAlarm;
            }
            //判断当前楼层Port状态,若为Down，或出料Port口outPutEnable是false的，则报警或弹窗。
            bool floorIsDownStatus = this.JudgeFloorStatusByAllPort();
            if (floorIsDownStatus)
            {
                //记录日志或弹窗提醒（楼层状态为Down,不能执行轿厢指令）
                LogHelper.loggerInfo("楼层状态为Down,不能执行轿厢指令,在方法[ShuttleDoCommandStatus]中");
                return ShuttleNextDoCommandStatus.PortAlarm;
            }
            //判断轿厢状态
            if (this.ShuttleMasterStatus == enumRIDState.DOWN)
            {
                //记录日志或弹窗提醒（轿厢状态为Down,不能执行轿厢指令）
                LogHelper.loggerInfo("轿厢状态为Down,不能执行轿厢指令,在方法[ShuttleDoCommandStatus]中");
                return ShuttleNextDoCommandStatus.ShuttleAlarm;
            }
            return ShuttleNextDoCommandStatus.OK;
        }
        /// <summary>
        /// add by yangshl 2023/9/21
        /// 判断轿厢是否能执行transfer指令
        /// </summary>
        public ShuttleNextCommandType DoNextCommand()
        {
            //CV以及轿厢对应关系是否符合transferOut/transferIn
            //获取unLoadCV所绑定的轿厢
            List<ConveyorBuffer> unloadCVs = this.GetCurrentFloorUnLoadCV();
            //获取loadCV所绑定的轿厢
            List<ConveyorBuffer> loadCVs = this.GetCurrentFloorLoadCV();
            ShuttleNextCommandType transferOutFlag = ShuttleNextCommandType.MOVE;
            ShuttleNextCommandType transferInFlag = ShuttleNextCommandType.MOVE;
            //transferOut是否能做
            foreach (ConveyorBuffer cv in loadCVs) 
            {
                //判断CV状态是否为Down,CV绑定的Port是否为outEnable状态，PortMode是否为Out
                LifterPort lifterPort = this.lftSem.GetLifterPort(cv.LifterPortID);
                /*                if (lifterPort.LifterPortState == enumRIDState.DOWN || !lifterPort.IsOutputEnable || lifterPort.PortInOutMode != enumLifterPortDirection.OUT)
                                {
                                    continue;
                                }
                                else
                                {

                                }*/
                //接料CV有物料
                if (lifterPort.IsCombine)
                {
                    if (cv.CstPresence && !string.IsNullOrEmpty(cv.CSTID))
                    {
                        //cv状态不是LoadRequest
                        if (!cv.CvLoadStatus)
                        {
                            foreach (string vehicleID in cv.Shuttles)
                            {
                                //判断接料CV对应的轿厢是否有物料
                                Vehicle vehicle = this.lftSem.GetVehicle(vehicleID);
                                if (vehicle != null && vehicle.IsCSTPresenceOn)
                                {
                                    //等待，循环判断状态
                                    transferOutFlag = ShuttleNextCommandType.WAIT;
                                }
                            }
                        }
                        else
                        {
                            //记录Log或弹窗提示,CV有物料，但是CV状态为Load状态
                            LogHelper.loggerInfo("CV有物料，但是CV状态为Load状态");
                            if (transferOutFlag != ShuttleNextCommandType.WAIT)
                            {
                                continue;
                            }
                        }
                    }
                    else
                    {
                        //判断接料CV绑定的轿厢内是否有物料
                        foreach (string vehicleID in cv.Shuttles)
                        {
                            Vehicle vehicle = this.lftSem.GetVehicle(vehicleID);
                            //轿厢内没有物料
                            if (vehicle != null && (!vehicle.IsCSTPresenceOn || string.IsNullOrEmpty(vehicle.CarrierID)))
                            {
                                if (transferOutFlag != ShuttleNextCommandType.WAIT)
                                {
                                    transferOutFlag = ShuttleNextCommandType.MOVE;
                                }
                            }
                            else
                            {
                                transferOutFlag = ShuttleNextCommandType.TRANSFER;
                            }
                        }
                    }
                    if (transferOutFlag == ShuttleNextCommandType.TRANSFER)
                    {
                        break;
                    }
                }
                else
                {
                    if (lifterPort.CarrierPresence[1] && !string.IsNullOrEmpty(lifterPort.CarrierId))
                    {
                        foreach (string vehicleID in cv.Shuttles)
                        {
                            //判断接料CV对应的轿厢是否有物料
                            Vehicle vehicle = this.lftSem.GetVehicle(vehicleID);
                            if (vehicle != null && vehicle.IsCSTPresenceOn)
                            {
                                //等待，循环判断状态
                                transferOutFlag = ShuttleNextCommandType.WAIT;
                            }
                        }
                    }
                    else
                    {
                        //判断接料CV绑定的轿厢内是否有物料
                        foreach (string vehicleID in cv.Shuttles)
                        {
                            Vehicle vehicle = this.lftSem.GetVehicle(vehicleID);
                            //轿厢内没有物料
                            if (vehicle != null && (!vehicle.IsCSTPresenceOn || string.IsNullOrEmpty(vehicle.CarrierID)))
                            {
                                if (transferOutFlag != ShuttleNextCommandType.WAIT)
                                {
                                    transferOutFlag = ShuttleNextCommandType.MOVE;
                                }
                            }
                            else
                            {
                                transferOutFlag = ShuttleNextCommandType.TRANSFER;
                            }
                        }
                    }
                    if (transferOutFlag == ShuttleNextCommandType.TRANSFER)
                    {
                        break;
                    }
                }
                
            }
            //transferIn是否能做
            bool returnFlag = false;
            foreach (ConveyorBuffer conveyorBuffer in unloadCVs)
            {
                if (returnFlag)
                {
                    break;
                }
                //判断CV状态是否为Down
                LifterPort lifterPort = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                if (lifterPort != null && lifterPort.LifterPortState == enumRIDState.DOWN)
                {
                    continue;
                }
                else
                {
                    //入料CV绑定的轿厢是否满
                    foreach (string vehicleID in conveyorBuffer.Shuttles)
                    {
                        Vehicle vehicle = this.lftSem.GetVehicle(vehicleID);
                        //判断是否只使用后面轿厢搬送
                        if (this.IsOnlyUseBehindVehicle)
                        {
                            if (Vehicle.Constants.BEHIND.Equals(vehicle.ShuttleAroundPosition))
                            {
                                //入料轿厢满的情况
                                if (vehicle != null && (vehicle.IsCSTPresenceOn && !string.IsNullOrEmpty(vehicle.CarrierID)))
                                {
                                    if (transferInFlag != ShuttleNextCommandType.WAIT)
                                    {
                                        transferInFlag = ShuttleNextCommandType.MOVE;
                                    }
                                }
                                else//入料轿厢不满
                                {
                                    //判断unLoadCV是否有物料
                                    if (conveyorBuffer.CstPresence && !string.IsNullOrEmpty(conveyorBuffer.CSTID))
                                    {
                                        transferInFlag = ShuttleNextCommandType.TRANSFER;
                                    }
                                    else
                                    {
                                        transferInFlag = ShuttleNextCommandType.WAIT;
                                    }
                                }
                            }
                        }
                        else
                        {
                            //入料轿厢满的情况
                            if (vehicle != null && (vehicle.IsCSTPresenceOn && !string.IsNullOrEmpty(vehicle.CarrierID)))
                            {
                                if (transferInFlag != ShuttleNextCommandType.WAIT)
                                {
                                    transferInFlag = ShuttleNextCommandType.MOVE;
                                }
                            }
                            else//入料轿厢不满
                            {
                                //判断unLoadCV是否有物料
                                if (conveyorBuffer.CstPresence && !string.IsNullOrEmpty(conveyorBuffer.CSTID))
                                {
                                    transferInFlag = ShuttleNextCommandType.TRANSFER;
                                }
                                else
                                {
                                    transferInFlag = ShuttleNextCommandType.WAIT;
                                }
                            }
                        }
                        if (transferInFlag == ShuttleNextCommandType.TRANSFER)
                        {
                            returnFlag = true;
                            break;
                        }
                    }
                }
            }
            //case1:入料是move并且出料也是move, ===》则直接Move
            if (transferInFlag == ShuttleNextCommandType.MOVE && transferOutFlag == ShuttleNextCommandType.MOVE)
            {
                this.NextCommandType = ShuttleNextCommandType.MOVE;
            }
            //case2:入料是transfer或者出料是transfer, ===》则transfer
            else if (transferInFlag == ShuttleNextCommandType.TRANSFER || transferOutFlag == ShuttleNextCommandType.TRANSFER)
            {
                this.NextCommandType = ShuttleNextCommandType.TRANSFER;
            }
            else
            {
                //出料是wait
                if (transferOutFlag == ShuttleNextCommandType.WAIT)
                {
                    this.NextCommandType = ShuttleNextCommandType.TRANSFEROUTWAIT;
                }
                //入料是wait
                else if (transferInFlag == ShuttleNextCommandType.WAIT)
                {
                    this.NextCommandType = ShuttleNextCommandType.TRANSFERINWAIT;
                }
                else
                {
                    //记录Log或弹窗提示,无法判断下一步执行逻辑
                }
            }
            return NextCommandType;
        }
        /// <summary>
        /// 获取当前楼层loadCV
        /// </summary>
        /// <returns></returns>
        public List<ConveyorBuffer> GetCurrentFloorLoadCV()
        {
            //获取当前楼层的入料CV
            List<ConveyorBuffer> loadCVs = new List<ConveyorBuffer>();
            foreach (ConveyorBuffer conveyorBuffer in this.lftSem.ConveyorBuffers.Values)
            {
                if (ConveyorBuffer.Constants.CVLOAD.Equals(conveyorBuffer.Cvtype) && conveyorBuffer.Floor == this.ShuttleFloor)
                {
                    loadCVs.Add(conveyorBuffer);
                }
            }
            return loadCVs;
        }
        /// <summary>
        /// 获取当前楼层unloadCV
        /// </summary>
        /// <returns></returns>
        public List<ConveyorBuffer> GetCurrentFloorUnLoadCV()
        {
            //获取当前楼层的出料CV
            List<ConveyorBuffer> unloadCVs = new List<ConveyorBuffer>();
            foreach (ConveyorBuffer conveyorBuffer in this.lftSem.ConveyorBuffers.Values)
            {
                if (ConveyorBuffer.Constants.CVUNLOAD.Equals(conveyorBuffer.Cvtype) && conveyorBuffer.Floor == this.ShuttleFloor)
                {
                    unloadCVs.Add(conveyorBuffer);
                }
            }
            return unloadCVs;
        }
        /// <summary>
        /// add by yangshl 2023/9/18
        /// 执行轿厢get/put指令
        /// </summary>
        public void DoShuttleTransfer()
        {
            //获取所有位置在前面/后面的轿厢
            List<string> frontShuttleIDs = new List<string>();
            List<string> behindShuttleIDs = new List<string>();
            foreach (Vehicle vehicle in this.lftSem.Vehicles.Values)
            {
                //轿厢在前面的轿厢
                if (Vehicle.Constants.FRONT.Equals(vehicle.ShuttleAroundPosition))
                {
                    frontShuttleIDs.Add(vehicle.ID);
                }
                else//轿厢在后面的轿厢
                {
                    behindShuttleIDs.Add(vehicle.ID);
                }
            }

            //获取当前楼层的出料CV
            List<ConveyorBuffer> unloadCVs = new List<ConveyorBuffer>();
            unloadCVs = this.GetCurrentFloorUnLoadCV();
            //获取当前楼层的入料CV
            List<ConveyorBuffer> loadCVs = new List<ConveyorBuffer>();
            loadCVs = this.GetCurrentFloorLoadCV();

            bool transferInPortDownFlag = false;//入料Port口Down标识
            bool transferOutPortDownFlag = false;//出料Port口Down标识
            bool actionStartFlag = false;//transfer指令开始启动标识
            //给PLC下达轿厢入料指令
            this.DoShuttleTransferIn(unloadCVs, frontShuttleIDs, behindShuttleIDs, ref actionStartFlag, ref transferInPortDownFlag);
            //给PLC下达轿厢出料指令
            this.DoShuttleTransferOut(loadCVs, frontShuttleIDs, behindShuttleIDs, ref actionStartFlag, ref transferOutPortDownFlag);

            if (transferOutPortDownFlag)
            {
                this.ShuttleTransferDown = ShuttleTransferDownFlag.transferOutPortDown;
                LogHelper.loggerInfo("在[DoShuttleTransfer]方法中，做transfer操作时，出料Port口Down");
            }
            else if (transferInPortDownFlag)
            {
                if (this.ShuttleTransferDown != ShuttleTransferDownFlag.transferOutPortDown)
                {
                    this.ShuttleTransferDown = ShuttleTransferDownFlag.transferInPortDown;
                    LogHelper.loggerInfo("在[DoShuttleTransfer]方法中，做transfer操作时，入料Port口Down");
                }
            }
            else
            {
                this.ShuttleTransferDown = ShuttleTransferDownFlag.None;
            }

            //transfer指令启动
            if (actionStartFlag)
            {
                Console.WriteLine("TRANSFER开始指令启动");
                LogHelper.loggerInfo("TRANSFER开始指令启动");
                this.O_TRANSFERSTARTREQ = true;
                this.transferStatus = ShuttleTransferStatus.Transfer;
                this.transferTimeOutCount = 0;
            }
            else
            {
                this.WaitForDoTransferTimer.Start();
                //等待时间
                this.transferTimeOutCount++;
            }
        }
        /// <summary>
        /// add by yangshl 2023/9/21
        /// 给PLC下轿厢入料指令
        /// </summary>
        /// <param name="loadCVs">获取当前楼层的入料CV集合</param>
        /// <param name="frontShuttleIDs">位置在前面的轿厢集合</param>
        /// <param name="behindShuttleIDs">位置在后面的轿厢集合</param>
        private void DoShuttleTransferIn(List<ConveyorBuffer> unloadCVs,List<string> frontShuttleIDs, List<string> behindShuttleIDs, ref bool actionStartFlag, ref bool transferInPortDownFlag)
        {
            try
            {
                //获取所有的Load指令
                List<TransferWorkItem> loadWorks = this.lftSem.LDispatcher.GetTransferCommandByStatus(enumTransferState.LOADREQ);
                bool isJudgeBehid = false;//是否继续判断后面的轿厢指令是否存在
                                          //遍历所有unloadCV
                foreach (ConveyorBuffer conveyorBuffer in unloadCVs)
                {
                    //判断loadCV是否为当前楼层
                    if (conveyorBuffer.Floor == this.ShuttleFloor)
                    {
                        foreach (TransferWorkItem transferWorkItem in loadWorks)
                        {
                            Carrier loadCarrier = Naming.GetCarrierManager().GetCarrier(transferWorkItem.CarrierID);
                            //判断当前楼层的loadCV是否有指令
                            if (loadCarrier != null && loadCarrier.CarrierLoc == conveyorBuffer.HostID)
                            {
                                //判断conveyorBuffer对应的Port口状态是否为down
                                LifterPort lifterPort = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                                if (lifterPort == null)
                                {
                                    //弹窗提醒，或记录Log日志（执行TransferIn动作时，指令绑定的物料location对应的Port口不存在）
                                    LogHelper.loggerInfo($"执行TransferIn动作时，指令[{transferWorkItem.CommandID}]绑定的物料[{transferWorkItem.CarrierID}]location[{loadCarrier.CarrierLoc}]对应的Port口不存在");
                                }
                                if (lifterPort != null && lifterPort.LifterPortState == enumRIDState.DOWN)
                                {
                                    transferInPortDownFlag = true;
                                    break;
                                }

                                //获取当前楼层CV绑定的轿厢
                                List<string> bindShuttles = conveyorBuffer.Shuttles;
                                Vehicle frontVehicle = null;
                                //先判断front轿厢有无物料
                                foreach (string shuttleID in frontShuttleIDs)
                                {
                                    if (bindShuttles.Contains(shuttleID))
                                    {
                                        //当前楼层front轿厢为空
                                        frontVehicle = this.lftSem.GetVehicle(shuttleID);
                                        if (frontVehicle != null && string.IsNullOrEmpty(frontVehicle.CommandId))
                                        {
                                            isJudgeBehid = true;
                                            break;
                                        }
                                        else//当前楼层front轿厢不为空
                                        {
                                            isJudgeBehid = false;
                                        }
                                    }
                                }
                                //是否需要继续判断behind轿厢
                                if (isJudgeBehid)
                                {
                                    foreach (string shuttleID in behindShuttleIDs)
                                    {
                                        if (bindShuttles.Contains(shuttleID))
                                        {
                                            //当前楼层behind轿厢为空
                                            Vehicle vehicle = this.lftSem.GetVehicle(shuttleID);
                                            if (vehicle != null && string.IsNullOrEmpty(vehicle.CommandId) && string.IsNullOrEmpty(vehicle.CarrierID) || !vehicle.IsCSTPresenceOn)
                                            {
                                                //behind轿厢下达transferIn指令
                                                try
                                                {
                                                    vehicle.O_CVFROM = (short)Convert.ToInt32(conveyorBuffer.PlcID);//transferIn指令起始地
                                                    vehicle.O_CVTO = (short)Convert.ToInt32(vehicle.PlcID);//transferIn指令目的地
                                                    actionStartFlag = true; //设置transfer指令开始启动标识为True
                                                                            //设置轿厢是否为出料动作
                                                    vehicle.IsTransferOutAction = false;
                                                    string msg = string.Format("给PLC下轿厢入料指令,起始地[{0}],目的地[{1}]，启动标识[{2}],是否为出料动作[{3}],指令ID[{4}]", conveyorBuffer.PlcID, vehicle.PlcID, actionStartFlag, vehicle.IsTransferOutAction, transferWorkItem.CommandID);
                                                    LogHelper.loggerInfo(msg);
                                                    if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                                                    {
                                                        this.ShuttleActiveCommand.CommandID = transferWorkItem.CommandID;
                                                        this.ShuttleActiveCommand.Dest = transferWorkItem.Dest;
                                                        //上报MCS shuttleActive事件
                                                        this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                                                        LogHelper.loggerInfo("上报MCS shuttleActive(407)事件");
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    //记录Log或弹窗提醒
                                                    Console.WriteLine("在DoShuttleTransferIn方法，给PLC下Transfer指令时报错" + ex.Message);
                                                    LogHelper.loggerError("在DoShuttleTransferIn方法，给PLC下Transfer指令时报错", ex);
                                                }
                                            }
                                            else//当前楼层behind轿厢不为空
                                            {
                                                //front轿厢下达transferIn指令
                                                try
                                                {
                                                    if (!this.IsOnlyUseBehindVehicle)
                                                    {
                                                        if (frontVehicle != null && string.IsNullOrEmpty(frontVehicle.CommandId) && string.IsNullOrEmpty(frontVehicle.CarrierID) || !frontVehicle.IsCSTPresenceOn)
                                                        {
                                                            frontVehicle.O_CVFROM = (short)Convert.ToInt32(conveyorBuffer.PlcID);//transferIn指令起始地
                                                            if (frontVehicle != null)
                                                            {
                                                                frontVehicle.O_CVTO = (short)Convert.ToInt32(frontVehicle.PlcID);//transferIn指令目的地
                                                            }
                                                            else
                                                            {
                                                                frontVehicle.O_CVTO = (short)0;//transferIn指令目的地
                                                            }
                                                            actionStartFlag = true; //设置transfer指令开始启动标识为True
                                                                                    //设置轿厢是否为出料动作
                                                            vehicle.IsTransferOutAction = false;
                                                            string msg = string.Format("给PLC下轿厢出料指令,起始地[{0}],目的地[{1}]，启动标识[{2}],是否为出料动作[{3}],指令ID[{4}]", conveyorBuffer.PlcID, frontVehicle.PlcID, actionStartFlag, vehicle.IsTransferOutAction, transferWorkItem.CommandID);
                                                            LogHelper.loggerInfo(msg);
                                                            if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                                                            {
                                                                this.ShuttleActiveCommand.CommandID = transferWorkItem.CommandID;
                                                                this.ShuttleActiveCommand.Dest = transferWorkItem.Dest;
                                                                //上报MCS shuttleActive事件
                                                                this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                                                                LogHelper.loggerInfo("上报MCS shuttleActive(407)事件");
                                                            }
                                                        }
                                                        else
                                                        {
                                                            LogHelper.loggerInfo("在DoShuttleTransferIn方法中,轿厢状态不对（有在籍或有物料）");
                                                            Console.WriteLine("在DoShuttleTransferIn方法,轿厢状态不对（有在籍或有物料）");
                                                        }
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    //记录Log或弹窗提醒
                                                    Console.WriteLine("在DoShuttleTransferIn方法，给PLC下Transfer指令时报错" + ex.Message);
                                                    LogHelper.loggerError("在DoShuttleTransferIn方法，给PLC下Transfer指令时报错",ex);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                LogHelper.loggerInfo($"在DoShuttleTransferIn方法中，指令[{transferWorkItem.CommandID}]绑定的物料ID为空");
                            }
                        }
                    }
                    else
                    {
                        //记录Log或弹窗提醒(loadCV不为当前楼层)
                        LogHelper.loggerInfo("loadCV不为当前楼层");
                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("在DoShuttleTransferIn方法中报错：" + ex.Message);
                LogHelper.loggerError("在DoShuttleTransferIn方法中报错", ex);
            }
        }
        /// <summary>
        /// add by yangshl 2023/9/20
        /// 给PLC下轿厢出料指令
        /// </summary>
        /// <param name="unloadCVs">获取当前楼层的出料CV集合</param>
        /// <param name="frontShutttleIDs">位置在前面的轿厢集合</param>
        /// <param name="behindShutttleIDs">位置在后面的轿厢集合</param>
        private void DoShuttleTransferOut(List<ConveyorBuffer> loadCVs,List<string> frontShutttleIDs,List<string> behindShutttleIDs, ref bool actionStartFlag, ref bool transferOutPortDownFlag)
        {
            try
            {
                //根据CV找到CV绑定的轿厢
                foreach (ConveyorBuffer conveyorBuffer in loadCVs)
                {
                    //判断CV是否为当前楼层
                    if (conveyorBuffer.Floor != this.ShuttleFloor)
                    {
                        continue;
                    }
                    //获取CV绑定的轿厢集合
                    List<string> bindShuttles = conveyorBuffer.Shuttles;
                    if (bindShuttles != null && bindShuttles.Count > 0)
                    {
                        bool isJudgeBehid = false;//是否继续判断后面的轿厢指令是否存在
                        //遍历front轿厢
                        foreach (string shuttleID in frontShutttleIDs)
                        {
                            //在FrontCV集合里筛选CV绑定的轿厢
                            if (bindShuttles.Contains(shuttleID))
                            {
                                Vehicle vehicle = this.lftSem.GetVehicle(shuttleID);
                                //判断front轿厢是否有指令
                                if (vehicle != null && !string.IsNullOrEmpty(vehicle.CommandId))
                                {
                                    TransferWorkItem transferWorkItem = this.lftSem.LDispatcher.GetJob(vehicle.CommandId);
                                    
                                    LifterPort lifterPort = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                                    LifterPort commandDestPort = this.lftSem.GetLifterPort(transferWorkItem.Dest);
                                    if (commandDestPort == null)
                                    {
                                        //指令的目的地不存在
                                        LogHelper.loggerInfo($"执行TransferOut动作时，指令[{transferWorkItem.CommandID}]的目的地[{transferWorkItem.Dest}]不存在");
                                        continue;
                                    }
                                    //判断指令的目的地楼层是否为当前楼层
                                    if (commandDestPort.Floor != this.ShuttleFloor)
                                    {
                                        //指令的目的地楼层不等于当前楼层
                                        LogHelper.loggerInfo($"执行TransferOut动作时，指令[{transferWorkItem.CommandID}]的目的地楼层[{commandDestPort.Floor}]不等于当前楼[{this.ShuttleFloor}]");
                                        continue;
                                    }

                                    if (lifterPort == null)
                                    {
                                        //执行TransferOut动作时，指令绑定的物料location对应的Port口不存在
                                        LogHelper.loggerInfo($"执行TransferOut动作时，指令[{transferWorkItem.CommandID}]绑定的物料[{transferWorkItem.CarrierID}]对应的Port口不存在");
                                    }
                                    //判断conveyorBuffer对应的Port口状态是否为Down
                                    if (lifterPort != null && lifterPort.LifterPortState == enumRIDState.DOWN)
                                    {
                                        transferOutPortDownFlag = true;
                                        break;
                                    }

                                    //下轿厢transferOut指令
                                    try
                                    {
                                        LifterPort lifterPortByCV = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                                        if (lifterPortByCV != null && lifterPortByCV.IsCombine)
                                        {
                                            //判断出料CV是否有料；判断出料Port口能否排出，判断出料CV状态是否允许接料状态,出料CV是否有物料
                                            if (lifterPortByCV != null && !conveyorBuffer.CstPresence && lifterPortByCV.IsOutputEnable && conveyorBuffer.CvLoadStatus)
                                            {
                                                vehicle.O_CVFROM = (short)Convert.ToInt32(vehicle.PlcID);//transferOut指令起始地
                                                vehicle.O_CVTO = (short)Convert.ToInt32(conveyorBuffer.PlcID);//transferOut指令目的地
                                                actionStartFlag = true; //设置transfer指令开始启动标识为True
                                                //设置轿厢是否为出料动作
                                                vehicle.IsTransferOutAction = true;
                                                string msg = string.Format("给PLC下轿厢出料指令,起始地[{0}],目的地[{1}]，启动标识[{2}],是否为出料动作[{3},指令ID[{4}]]",vehicle.PlcID, conveyorBuffer.PlcID, actionStartFlag, vehicle.IsTransferOutAction, vehicle.CommandId);
                                                LogHelper.loggerInfo(msg);
                                                /*if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                                                {
                                                    this.ShuttleActiveCommand.CommandID = vehicle.CommandId;
                                                    //上报MCS shuttleActive事件
                                                    this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                                                }*/
                                                isJudgeBehid = false;
                                                break;
                                            }
                                            else
                                            {
                                                //记录Log或弹窗提醒
                                                Console.WriteLine("CV绑定的Port口为空，或出料CV不能接料，或当前Port口状态是不能出料状态");
                                                LogHelper.loggerInfo("CV绑定的Port口为空，或出料CV不能接料，或当前Port口状态是不能出料状态");
                                            }
                                        }
                                        else
                                        {
                                            //判断出料Port是否有料；判断出料Port口能否排出，判断出料CV状态是否允许接料状态
                                            if (lifterPortByCV != null &&  !lifterPortByCV.CarrierPresence[1] && lifterPortByCV.IsOutputEnable && conveyorBuffer.CvLoadStatus)
                                            {
                                                vehicle.O_CVFROM = (short)Convert.ToInt32(vehicle.PlcID);//transferOut指令起始地
                                                vehicle.O_CVTO = (short)Convert.ToInt32(conveyorBuffer.PlcID);//transferOut指令目的地
                                                actionStartFlag = true; //设置transfer指令开始启动标识为True
                                                //设置轿厢是否为出料动作
                                                vehicle.IsTransferOutAction = true;
                                                string msg = string.Format("给PLC下轿厢出料指令,起始地[{0}],目的地[{1}]，启动标识[{2}],是否为出料动作[{3},指令ID[{4}]]", vehicle.PlcID, conveyorBuffer.PlcID, actionStartFlag, vehicle.IsTransferOutAction, vehicle.CommandId);
                                                LogHelper.loggerInfo(msg);
                                                /*if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                                                {
                                                    this.ShuttleActiveCommand.CommandID = vehicle.CommandId;
                                                    //上报MCS shuttleActive事件
                                                    this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                                                }*/
                                                isJudgeBehid = false;
                                                break;
                                            }
                                            else
                                            {
                                                //记录Log或弹窗提醒
                                                Console.WriteLine("CV绑定的Port口为空，或出料CV不能接料，或当前Port口状态是不能出料状态");
                                                LogHelper.loggerInfo("CV绑定的Port口为空，或出料CV不能接料，或当前Port口状态是不能出料状态");
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        //记录Log或弹窗提醒
                                        Console.WriteLine("在DoShuttleTransferOut方法，给PLC下Transfer指令时报错" + ex.Message);
                                        LogHelper.loggerError("在DoShuttleTransferOut方法，给PLC下Transfer指令时报错",ex);
                                    }
                                }
                                else
                                {
                                    //判断behind轿厢是否有指令
                                    isJudgeBehid = true;
                                }
                            }
                        }
                        //是否需要继续判断后面的轿厢是否有指令
                        if (isJudgeBehid)
                        {
                            //遍历behind轿厢
                            foreach (string shuttleID in behindShutttleIDs)
                            {
                                //在BehindCV集合里筛选CV绑定的轿厢
                                if (bindShuttles.Contains(shuttleID))
                                {
                                    Vehicle vehicle = this.lftSem.GetVehicle(shuttleID);
                                    //判断Behind轿厢是否有指令
                                    if (vehicle != null && !string.IsNullOrEmpty(vehicle.CommandId))
                                    {
                                        TransferWorkItem transferWorkItem = this.lftSem.LDispatcher.GetJob(vehicle.CommandId);

                                        LifterPort lifterPort = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                                        LifterPort commandDestPort = this.lftSem.GetLifterPort(transferWorkItem.Dest);
                                        if (commandDestPort == null)
                                        {
                                            //指令的目的地不存在
                                            LogHelper.loggerInfo($"执行TransferOut动作时，指令[{transferWorkItem.CommandID}]的目的地[{transferWorkItem.Dest}]不存在");
                                            continue;
                                        }
                                        //判断指令的目的地楼层是否为当前楼层
                                        if (commandDestPort.Floor != this.ShuttleFloor)
                                        {
                                            //指令的目的地楼层不等于当前楼层
                                            LogHelper.loggerInfo($"执行TransferOut动作时，指令[{transferWorkItem.CommandID}]的目的地楼层[{commandDestPort.Floor}]不等于当前楼[{this.ShuttleFloor}]");
                                            continue;
                                        }

                                        if (lifterPort == null)
                                        {
                                            //执行TransferOut动作时，指令绑定的物料location对应的Port口不存在
                                            LogHelper.loggerInfo($"执行TransferOut动作时，指令[{transferWorkItem.CommandID}]绑定的物料[{transferWorkItem.CarrierID}]对应的Port口不存在");
                                        }
                                        //判断conveyorBuffer对应的Port口状态是否为Down
                                        if (lifterPort != null && lifterPort.LifterPortState == enumRIDState.DOWN)
                                        {
                                            transferOutPortDownFlag = true;
                                            break;
                                        }

                                        //下轿厢transferOut指令
                                        try
                                        {
                                            LifterPort lifterPortOut = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                                            if (lifterPortOut != null && lifterPortOut.IsCombine)
                                            {
                                                //判断出料CV是否有料；判断出料Port口能否排出
                                                if (!conveyorBuffer.CstPresence && this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID).IsOutputEnable)
                                                {
                                                    vehicle.O_CVFROM = (short)Convert.ToInt32(vehicle.PlcID);//transferOut指令起始地
                                                    vehicle.O_CVTO = (short)Convert.ToInt32(conveyorBuffer.PlcID);//transferOut指令目的地
                                                    actionStartFlag = true; //设置transfer指令开始启动标识为True
                                                    //设置轿厢是否为出料动作
                                                    vehicle.IsTransferOutAction = true;
                                                    string msg = string.Format("给PLC下轿厢出料指令,起始地[{0}],目的地[{1}]，启动标识[{2}],是否为出料动作[{3},指令ID[{4}]", vehicle.PlcID, conveyorBuffer.PlcID, actionStartFlag, vehicle.IsTransferOutAction, vehicle.CommandId);
                                                    LogHelper.loggerInfo(msg);
                                                    /*if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                                                    {
                                                        this.ShuttleActiveCommand.CommandID = vehicle.CommandId;
                                                        //上报MCS shuttleActive事件
                                                        this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                                                    }*/
                                                    break;
                                                }
                                            }
                                            else
                                            {
                                                LifterPort lifterPortByCV = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                                                //判断出料Port是否有料；判断出料Port口能否排出
                                                if (lifterPortByCV != null && !lifterPortOut.CarrierPresence[1] && lifterPortByCV.IsOutputEnable)
                                                {
                                                    vehicle.O_CVFROM = (short)Convert.ToInt32(vehicle.PlcID);//transferOut指令起始地
                                                    vehicle.O_CVTO = (short)Convert.ToInt32(conveyorBuffer.PlcID);//transferOut指令目的地
                                                    actionStartFlag = true; //设置transfer指令开始启动标识为True
                                                    //设置轿厢是否为出料动作
                                                    vehicle.IsTransferOutAction = true;
                                                    string msg = string.Format("给PLC下轿厢出料指令,起始地[{0}],目的地[{1}]，启动标识[{2}],是否为出料动作[{3},指令ID[{4}]", vehicle.PlcID, conveyorBuffer.PlcID, actionStartFlag, vehicle.IsTransferOutAction, vehicle.CommandId);
                                                    LogHelper.loggerInfo(msg);
                                                    /*if (string.IsNullOrEmpty(this.ShuttleActiveCommand.CommandID))
                                                    {
                                                        this.ShuttleActiveCommand.CommandID = vehicle.CommandId;
                                                        //上报MCS shuttleActive事件
                                                        this.lftSem.SecsDriver.SendMessage("S6F11", "407", this);
                                                    }*/
                                                    break;
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            //记录Log或弹窗提醒
                                            Console.WriteLine("在DoShuttleTransferOut方法，给PLC下Transfer指令时报错" + ex.Message);
                                            LogHelper.loggerError("在DoShuttleTransferOut方法，给PLC下Transfer指令时报错",ex);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        //记录Log或弹窗提醒，出料CV没有绑定轿厢
                        LogHelper.loggerInfo("出料CV没有绑定轿厢");
                    }
                }
            }
            catch (Exception ex)
            {
                //记录Log或弹窗提醒
                Console.WriteLine("在DoShuttleTransferIn方法报错" + ex.Message);
                LogHelper.loggerError("在DoShuttleTransferIn方法报错", ex);
            }
        }
        /// <summary>
        /// 手动创建轿厢move指令
        /// </summary>
        public bool ManualCreateVehicelMoveCommand(string dest)
        {
            bool flag = false;
            try
            {
                this.O_MOVETO = Convert.ToInt16(dest);
                this.O_MOVESTARTREQ = true;
                this.transferStatus = ShuttleTransferStatus.Move;
                flag = true;
                LogHelper.loggerInfo($"手动创建轿厢移动指令成功，并下发指令目的地[{dest}]信息给PLC");
            }
            catch (Exception ex)
            {
                LogHelper.loggerError($"手动创建轿厢move指令时，将用户输入的值[{dest}]转为PLCID值报错",ex);
            }
            return flag;
        }
        /// <summary>
        /// 手动创建轿厢Transfer指令
        /// </summary>
        public bool ManualCreateVehicelTransferCommand(string source, string dest)
        {
            bool flag = false;
            LocationUnit sourceLocationUnit = this.lftSem.GetLocationUnit(source);
            LocationUnit destLocationUnit = this.lftSem.GetLocationUnit(dest);

            //判断起始地或目的地是否都为CV或轿厢
            if (sourceLocationUnit is ConveyorBuffer && destLocationUnit is ConveyorBuffer)
            {
                LogHelper.loggerInfo($"手动创建轿厢指令失败，起始地[{sourceLocationUnit}]和目的地[{destLocationUnit}]都为CV");
                return flag;
            }
            if (sourceLocationUnit is Vehicle && destLocationUnit is Vehicle)
            {
                LogHelper.loggerInfo($"手动创建轿厢指令失败，起始地[{sourceLocationUnit}]和目的地[{destLocationUnit}]都为轿厢");
                return flag;
            }

            short sourcePLCID = 0;
            short destPLCID = 0;
            Vehicle sourceVehicle = null;
            Vehicle destVehicle = null;
            ConveyorBuffer sourceCV = null;
            ConveyorBuffer destCV = null;

            try
            {
                if (sourceLocationUnit is ConveyorBuffer)
                {
                    sourceCV = (ConveyorBuffer)sourceLocationUnit;
                    sourcePLCID = Convert.ToInt16(sourceCV.PlcID);
                }
                else if (sourceLocationUnit is Vehicle)
                {
                    sourceVehicle = (Vehicle)sourceLocationUnit;
                    sourcePLCID = Convert.ToInt16(sourceVehicle.PlcID);
                }
                else
                {
                    LogHelper.loggerInfo("在手动创建轿厢搬送指令时，起始地或目的地有误");
                }

                if (destLocationUnit is ConveyorBuffer)
                {
                    destCV = (ConveyorBuffer)destLocationUnit;
                    destPLCID = Convert.ToInt16(destCV.PlcID);
                }
                else if (destLocationUnit is Vehicle)
                {
                    destVehicle = (Vehicle)destLocationUnit;
                    destPLCID = Convert.ToInt16(destVehicle.PlcID);
                }
                else
                {
                    LogHelper.loggerInfo("在手动创建轿厢搬送指令时，起始地或目的地有误");
                }

                //给设备下达起始地值和目的地值
                if (sourcePLCID != 0 && destPLCID != 0)
                {
                    if (sourceVehicle != null && destCV != null)
                    {
                        //判断起始地和目的地是否允许搬送
                        if (sourceVehicle.IsCSTPresenceOn && !string.IsNullOrEmpty(sourceVehicle.CarrierID) && !destCV.CstPresence)
                        {
                            sourceVehicle.O_CVFROM = sourcePLCID;
                            sourceVehicle.O_CVTO = destPLCID;
                            sourceVehicle.IsTransferOutAction = true;
                            this.O_TRANSFERSTARTREQ = true;
                            this.transferStatus = ShuttleTransferStatus.Transfer;
                            flag = true;
                            LogHelper.loggerInfo($"手动创建轿厢搬送指令成功，并下发指令起始地[{sourcePLCID}],目的地[{destPLCID}]给PLC");
                        }
                        else
                        {
                            LogHelper.loggerInfo("手动创建轿厢搬送指令时，起始地没有物料，或目的地存在物料");
                        }
                    }
                    else if (destVehicle != null && sourceCV != null)
                    {
                        //判断起始地和目的地是否允许搬送
                        if (sourceCV.CstPresence && !string.IsNullOrEmpty(sourceCV.CSTID) && !destVehicle.IsCSTPresenceOn)
                        {
                            destVehicle.O_CVFROM = sourcePLCID;
                            destVehicle.O_CVTO = destPLCID;
                            destVehicle.IsTransferOutAction = false;
                            this.O_TRANSFERSTARTREQ = true;
                            this.transferStatus = ShuttleTransferStatus.Transfer;
                            flag = true;
                            LogHelper.loggerInfo($"手动创建轿厢搬送指令成功，并下发指令起始地[{sourcePLCID}],目的地[{destPLCID}]给PLC");
                        }
                        else
                        {
                            LogHelper.loggerInfo("手动创建轿厢搬送指令时，起始地没有物料，或目的地存在物料");
                        }
                    }
                    else
                    {
                        LogHelper.loggerInfo("手动创建轿厢搬送指令时，起始地或目的地不存在");
                    }
                }
                else
                {
                    LogHelper.loggerInfo("手动创建轿厢搬送指令时，起始地PLCID值为空，或目的地PLCID值为空");
                }
            }
            catch (Exception ex)
            {
                LogHelper.loggerError("在手动创建轿厢搬送指令时,在方法ManualCreateVehicelTransferCommand中报错", ex);
            }
            return flag;
        }
        /// <summary>
        /// 判断设备状态，以及轿厢状态是否能执行手动创建指令
        /// </summary>
        /// <returns></returns>
        public bool JudgeDoManualCommand()
        {
            bool flag = false;
            bool eqpStatus = this.lftSem.LDispatcher.JudgeEquipmentTransferStatus();
            //判断设备状态不为Down,设备运行模式为Auto模式，轿厢状态不为Down,轿厢搬送状态为Ready
            if (eqpStatus && this.ShuttleMasterStatus != enumRIDState.DOWN && this.transferStatus==ShuttleTransferStatus.Ready )
            {
                flag = true;
            }

            return flag;
        }
        protected override void Load(DBConnection theDB)
        {
            try
            {
                base.Load(theDB);//加载点位信息
            }
            catch (SqlException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 判断当前楼层所有入料CV上是否有物料
        /// </summary>
        /// <returns></returns>
        public bool JudgeMaterialOnCVOrPortByFloor()
        {
            bool flag = false;
            foreach (ConveyorBuffer conveyorBuffer in this.lftSem.ConveyorBuffers.Values)
            {
                //获取轿厢当前楼层的CV集合
                if (conveyorBuffer.Floor == this.ShuttleFloor)
                {
                    LifterPort lifterPortByCV = this.lftSem.GetLifterPort(conveyorBuffer.LifterPortID);
                    if (lifterPortByCV != null && lifterPortByCV.PortInOutMode == enumLifterPortDirection.IN)
                    {
                        if (conveyorBuffer.CstPresence && !string.IsNullOrEmpty(conveyorBuffer.CSTID))
                        {
                            flag = true;
                            return flag;
                        }
                        if (lifterPortByCV.CarrierPresence[1] && !string.IsNullOrEmpty(lifterPortByCV.CarrierId))
                        {
                            flag = true;
                            return flag;
                        }
                    }
                }
            }
            return flag;
        }
        /// <summary>
        /// 获取Vid值,返回的字典，键为字段名
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> getVidValueForHost()
        {
            Dictionary<string, string> VidValue = new Dictionary<string, string>();
            VidValue.Add("LifterName", this.lftSem.HostID);
            VidValue.Add("CommandID", this.ShuttleActiveCommand.CommandID);
            VidValue.Add("ShuttleID", this.HostID);
            VidValue.Add("LocationID", this.LocationID);
            VidValue.Add("LifterUnitID", this.HostID);
            VidValue.Add("ShuttleStatei", ((int)this.shuttleMasterStatusForAim).ToString());
            VidValue.Add("ShuttleLocationCommandID", this.ShuttleLocationCommandID);
            return VidValue;
        }

        internal ShuttleNextCommandType NextCommandType { get => nextCommandType; set => nextCommandType = value; }
        public bool AllowDoTransfer { get => allowDoTransfer; set => allowDoTransfer = value; }
        public enumRIDState ShuttleMasterStatus { get => shuttleMasterStatus; set => shuttleMasterStatus = value; }
        public TransferWorkItem ShuttleActiveCommand { get => shuttleActiveCommand; set => shuttleActiveCommand = value; }
        public string LocationID { get => locationID; set => locationID = value; }
        public string ShuttleLocationCommandID { get => shuttleLocationCommandID; set => shuttleLocationCommandID = value; }
        public ShuttleTransferDownFlag ShuttleTransferDown { get => shuttleTransferDown; set => shuttleTransferDown = value; }
        public bool ShuttleIsReadyFlag { get => shuttleIsReadyFlag; set => shuttleIsReadyFlag = value; }
        public CimToPLCCommandInfo ShuttleLocationCommand { get => shuttleLocationCommand; set => shuttleLocationCommand = value; }
        public ShuttleTransferStatus TransferStatus { get => transferStatus; set => transferStatus = value; }
        public int ShuttleDestFloor { get => shuttleDestFloor; set => shuttleDestFloor = value; }
    }
}
